package com.notes.spring.aop.aspects;

import com.notes.spring.aop.annotation.MyLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author
 * @Describe 功能描述
 * @date
 */
@Aspect
@Component
public class LogAspect {

    @Pointcut(value = "@annotation(com.notes.spring.aop.annotation.MyLog)")
    public void pointCut(){}

    @Before(value = "pointCut() && @annotation(mylog)", argNames = "mylog")
    public void before(MyLog myLog) {
        System.out.println("before " + myLog.name());
    }

    @After(value = "pointCut() && @annotation(mylog)", argNames = "mylog")
    public void after(MyLog myLog) {
        String name = myLog.name();
        System.out.println("after " + name);
    }

    // java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advice
    @Around(value = "pointCut() && @annotation(mylog2)", argNames = "pjp, mylog2")
    public Object around(ProceedingJoinPoint pjp, MyLog myLog2) throws Throwable {
        Signature signature = pjp.getSignature();
        MethodSignature ms = (MethodSignature) signature;
        Method method = ms.getMethod();

        MyLog log = method.getAnnotation(MyLog.class);
        String name = log.name();

        // 执行目标方法(如果不执行目标方法，before/AfterThrowing方法不会触发执行)
        Object proceed = pjp.proceed();

        System.out.println("around " + name + " & result " + (proceed == null ? "proceed为空" : proceed.toString()));

        // 此处的返回值为目标方法的最终返回后结果
        return 10086;
    }

    // 未处理的异常捕获处理，业务有处理异常则不会进行处理（try catch）
    @AfterThrowing(value = "pointCut() && @annotation(log)", argNames = "log,e", throwing = "e")
    public void afterThrowing(MyLog log, Throwable e) {
        String name = log.name();
        System.out.println("AfterThrowing " + name);
    }

}
